package com.neusoft.ch9.tools;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/*
 * 课堂笔记：
 * 一、工具类
 *   1、String类在内存中的存储模型
 *   1.1 队列、堆、栈
 *      数据结构的组合形式；（数据的存储结构）
 *      队列：先进先出；
 *      栈：先进后出；
 *      堆：树型储存形式；（树的遍历）  
 *   1.2 String在内存中的存储模型
 *      在jvm编译期一般使用栈来存储变量名（地址）；
 *      jvm编译期中对字符串的存储有两种方式：
 *         一种是存储在常量池中；（字符串常量池）
 *         一种是存储在内存堆中；
 *      存储模型：
 *         (1) 字符串常量都是存放在字符串常量池中；        
 *             字符串常量池中的字符串常量没有重复的；
 *             当编译期需要创建一个字符串常量时，先到字符串常量池中查找有没有该字符串，如果有，则直接使用；如果没有，创建后使用；
 *         (2) 使用new创建的字符串对象都是存储在堆中；堆内存中的字符串对象的内容可以重复；
 *             每次使用new都会在堆中创建一个新的对象；无论之前是否有内容相同的对象；
 *             
 *             new 字符串对象时，如果使用了带参的构造方法，如果参数是一个字符串常量，
 *             则需要先去字符串常量池中查找有无该字符串常量，
 *             如果有，则将其复制到堆内存中；如果没有，则先在字符串常量池中创建该字符串常量，然后再复制到堆内存中；
 *             
 *             使用 + 拼接的结果字符串对象也是放在堆中的；
 *   2、StringBuffer和StringBuilder的用法
 *      String字符串可以通过+拼接的形式将多个字符串拼接在一起； 
 *      +拼接字符串：因为字符串的长度是不可变的，不是动态增加的，所以每次都会重新创建一个变量进行存储；如果是多个字符串进行拼接，则效率比较低；
 *      StringBuilder的存储大小是可以动态改变的；如果拼接多个字符串，可以使用StringBuilder进行处理；          
 *      
 *      String和StringBuilder的区别：
 *      String是固定长度，不可改变；
 *      StringBuilder是变长的，可以动态扩展（默认长度16字符，也可以手动指定）
 *      
 *      StringBuffer是StringBuilder的线程安全类；
 *   3、其他工具类
 *   3.1 Math工具类
 *       数学计算相关的工具类；
 *       随机数的生成：
 *            Math.random() ; 
 *            Random类；   
 *   3.2 Date、SimpleDateFormat、Calendar工具类
 *       Date:日期类
 *       SimpleDateFormat:日期格式化类         
 *   3.3 Calender类 
 *       日历类，获取与时间相关一些数据；
 *       
 *   
 *     
 *     
 */
public class TestCh9 {

	public static void main(String[] args) {
		test05();
	}

	/**
	 * Calendar类
	 */
	private static void test05() {
		// 创建一个Calendar类的实例对象
		Calendar cal = Calendar.getInstance();
		// 设置calendar类的日期
		cal.set(1992, 4, 20); // set方法的月份也是从 0 - 11
		// 获取一些时间相关的参数
		// 获取时间
		Date date = cal.getTime();
		// 获取毫秒数
		long ls0 = cal.getTimeInMillis();
		long ls1 = System.currentTimeMillis();
		// 获取当前时间中的几号
		int day0 = cal.get(Calendar.DAY_OF_MONTH);
		System.out.println("日期：" + day0);
		// 获取月份：0-11
		int moth0 = cal.get(Calendar.MONTH);
		System.out.println("月份：" + (moth0 + 1));
		// 今天是今年中的第几天
		int dd = cal.get(Calendar.DAY_OF_YEAR);
		System.out.println("一年中的第几天：" + dd);
	}

	/**
	 * 日期类
	 */
	private static void test04() {
		Date date = new Date();
		System.out.println("当前系统时间：" + convertDate2String(date, "yyyy/MM/dd HH:mm:ss"));
		System.out.println("当前系统时间：" + convertDate2String(date, "当前时间：yyyy年MM月dd日 HH时mm分ss秒"));

		String strDate = "1990-04-24";
		Date date10 = convertString2Date(strDate, "yyyy-MM-dd");
		System.out.println("转换之后的日期对象：" + date10);
	}

	/**
	 * 将指定格式的字符串转为日期对象
	 * 
	 * @param strDate
	 *            日期字符串
	 * @param strFormat
	 *            字符串格式[指定的格式是字符串的格式]
	 * @return 日期对象
	 */
	private static Date convertString2Date(String strDate, String strFormat) {
		// 结果变量：默认null //当前时间
		Date date = null; // new Date();

		if (strDate != null && !strDate.equals("")) {
			// 格式串是否为null
			if (strFormat == null || strFormat.trim().equals("")) {
				strFormat = "yyyy-MM-dd HH:mm:ss";
			}
			// 创建日期格式化类的实例对象
			SimpleDateFormat sdf = new SimpleDateFormat(strFormat);
			// 将指定格式的字符串转换为日期
			try {
				date = sdf.parse(strDate);
			} catch (ParseException e) {
				// 异常处理
				System.out.println("将日期字符串转换为日期对象类型异常：" + e.getMessage());
				// e.printStackTrace();
			}
		}
		// 返回值
		return date;
	}

	/**
	 * 将日期对象转为指定格式的字符串
	 * 
	 * @param date
	 *            被转换的日期对象
	 * @param strFormat
	 *            格式串
	 * @return 结果字符串
	 */
	private static String convertDate2String(Date date, String strFormat) {
		// 结果变量
		String strDate;
		// 判定data是否为null
		if (date == null) {
			// 取系统当前时间
			date = new Date();
		}
		// 格式串是否为null
		if (strFormat == null || strFormat.trim().equals("")) {
			strFormat = "yyyy-MM-dd HH:mm:ss";
		}

		// 创建日期格式化类的实例对象
		SimpleDateFormat sdf = new SimpleDateFormat(strFormat);
		// 将日期转换为指定格式的字符串
		strDate = sdf.format(date);
		// 返回值
		return strDate;
	}

	/**
	 * 将日期对象转为指定格式的字符串
	 * 
	 * @param date
	 *            被转换的日期对象
	 * @param strFormat
	 *            格式串
	 * @return 结果字符串
	 */
	private static String convertDate2String2(Date date, String strFormat) {
		// 结果变量：默认结果为null
		String strDate = null;
		// 判定data是否为null
		if (date != null) {
			// 格式串是否为null
			if (strFormat == null || strFormat.trim().equals("")) {
				strFormat = "yyyy-MM-dd HH:mm:ss";
			}

			// 创建日期格式化类的实例对象
			SimpleDateFormat sdf = new SimpleDateFormat(strFormat);
			// 将日期转换为指定格式的字符串
			strDate = sdf.format(date);
		}
		// 返回值
		return strDate;
	}

	/**
	 * 存储模型
	 */
	private static void test03() {
		StringBuilder sb = new StringBuilder("xiao");
		sb.append("ming");
		sb.append(" ");
		sb.append("ni").append("hao").append("!");
		String str = sb.toString();
	}

	/**
	 * 存储模型
	 */
	private static void test01() {
		// 静态创建字符串
		String str00 = "xiaoming"; // 一个对象 字符串常量池
		String str01 = "xiaoming"; // 一个对象 字符串常量池
		// 动态创建字符串
		String str10 = new String("xiaoming"); // 二个对象 存储在堆中
		String str11 = new String("xiaoming"); // 三个对象 存储在堆中

		// + 拼接的字符串也存放在堆中
		String str20 = "xiao";// 字符串常量池
		String str21 = "ming";// 字符串常量池
		String str30 = str20 + str21; // 存储在堆中

		System.out.println("str00==str01:" + (str00 == str01));
		System.out.println("str00==str10:" + (str00 == str10));
		System.out.println("str00==str11:" + (str00 == str11));
		System.out.println("str10==str11:" + (str10 == str11));

		System.out.println("str00==str30:" + (str00 == str30));
		System.out.println("str10==str30:" + (str10 == str30));
	}

	/**
	 * 存储模型
	 */
	private static void test02() {
		// 动态创建字符串
		String str10 = new String("xiaoming"); // 2个对象（一个在字符串池中，一个在堆中）
		// 请问以上代码在内存中创建了几个对象？
		// 在内存中创建了2个对象
	}

}
